package fr.gestproj.bean.securite.spring;

import fr.gestproj.facade.UtilisateurFacade;
import fr.gestproj.model.Utilisateur;
import fr.gestproj.utils.UtilsAuthentication;
import fr.gestproj.utils.UtilsMetier;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 *
 * @author Parrot
 */
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    private ShaPasswordEncoder passwordEncoder;

    private UserDetailsService userDetailsService;

    private boolean includeDetailsObject = true;

    private Integer nombreMaxEchecConnexion;

    public CustomAuthenticationProvider() {
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) {
        Utilisateur user = (Utilisateur) userDetails;

        if (authentication.getCredentials() == null) {
            throw new BadCredentialsException("Veuillez renseigner le nom d'utilisateur et le mot de passe avant de vous authentifier");
        }
        String presentedPassword = authentication.getCredentials().toString();
        if (!user.getPassword().equals(UtilsAuthentication.chiffrerMotdepasse(presentedPassword, user.getDateCreation()))) {
            int nombreEchecConnexion = user.getNombreEchecConnexion() + 1;
            if (nombreEchecConnexion >= nombreMaxEchecConnexion) {
                throw new AuthenticationServiceException("Trop de tentative en echec de connexion. Veuillez contacter l'administrateur pour déverouiller votre compte.");
            }
            user = UtilsMetier.getBean(UtilisateurFacade.class).modificationNombreEchecConnexion(user, nombreEchecConnexion);
            throw new BadCredentialsException("Nom d'utilisateur ou mot de passe incorrect");
        }
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken pAuthentication) {
        Utilisateur user;
        if ((username == null) || username.isEmpty()) {
            throw new AuthenticationServiceException("Veuillez correctement renseigner le nom d'utilisateur");
        }
        try {
            user = UtilsMetier.getBean(UtilisateurFacade.class).getUtilisateurByUsername(username);
            if (user == null) {
                throw new BadCredentialsException("Nom d'utilisateur ou mot de passe incorrect");
            }
        } catch (DataAccessException repositoryProblem) {
            throw new AuthenticationServiceException("Problème d'accès aux données");
        }
        return user;
    }

    public ShaPasswordEncoder getPasswordEncoder() {
        return passwordEncoder;
    }

    public void setPasswordEncoder(ShaPasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    public UserDetailsService getUserDetailsService() {
        return this.userDetailsService;
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public boolean isIncludeDetailsObject() {
        return this.includeDetailsObject;
    }

    public void setIncludeDetailsObject(boolean includeDetailsObject) {
        this.includeDetailsObject = includeDetailsObject;
    }

    public Integer getNombreMaxEchecConnexion() {
        return nombreMaxEchecConnexion;
    }

    public void setNombreMaxEchecConnexion(Integer pNombreMaxEchecConnexion) {
        nombreMaxEchecConnexion = pNombreMaxEchecConnexion;
    }

}
